package com.bort.system.controller;

import com.bort.system.common.DataContainer;
import com.bort.system.info.CheckOutResult;
import com.bort.system.info.DeskInfo;
import com.bort.system.model.Cart;
import com.bort.system.model.TGameLog;
import com.bort.system.service.ClientService;
import com.bort.system.service.impl.ClientServiceImpl;
import com.bort.system.utils.Result;
import javafx.application.Platform;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
import javafx.util.Callback;
import lombok.Value;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.ResourceBundle;

public class CloseDialogController implements Initializable {

    ClientService clientService;

    DeskInfo data;

    List<Integer> hours = null;
    List<Integer> minutes = null;

    private Date closedTime;

    @FXML
    TextField orgTime;

    @FXML
    TextField amount;

    @FXML
    TextField realTime;

    @FXML
    TextField income;

    @FXML
    TextField total;

    @FXML
    TextField leftTime;

    @FXML
    TextField leftAmount;

    @FXML
    AnchorPane anchor;

    @FXML
    ComboBox<Integer> hour;

    @FXML
    ComboBox<Integer> minute;

    @FXML
    Button overtimeBtn;

    @FXML
    TableView<Cart> goodsTable;

    @FXML
    TableColumn<Cart,String> goodsNameCol;

    @FXML
    TableColumn<Cart, ImageView> goodsImgCol;

    @FXML
    TableColumn<Cart,BigDecimal> goodsPriceCol;

    @FXML
    TableColumn<Cart,Integer> goodsNumCol;

    @FXML
    TableColumn<Cart,BigDecimal> totalCol;

    @FXML
    TableColumn<Cart,String> playerNameCol;

    @FXML
    TableColumn<Cart,Button> actRefundBtn;

    @FXML
    Button submitBtn;

    @FXML
    void onCancelBtnClick(ActionEvent event){
        Scene scene = anchor.getScene();
        Stage window = (Stage)scene.getWindow();
        window.close();
    }

    @FXML
    void onConfirmBtnClick(ActionEvent event){
        submitBtn.setDisable(true);
        Integer two = 2;
        BigDecimal amount = new BigDecimal(income.getText());
        BigDecimal pay = null;
        if(two.equals(data.getTimeLimit())){
            String totalAmount = StringUtils.isNotEmpty(total.getText()) ? total.getText() : "0";
            pay = new BigDecimal(totalAmount);
        }else{
            pay = amount;
        }
        boolean end = clientService.closeDesk(data,closedTime,amount,pay);
        if(end){
            DeskController deskCtrl = closeDialog();
            deskCtrl.closeDesk();
        }
    }


    @FXML
    void onConfirmOvertimeBtnClick(ActionEvent event){
        Integer value = hour.getValue();
        Integer mValue = minute.getValue();
        TGameLog log = clientService.addOvertime(data, value, mValue);
        if(null != log){
            DeskController descCtrl = closeDialog();
            data.setEndTime(log.getEndTime());
            descCtrl.overtimeClose();
        }
    }


    @FXML
    void onHourSelect(ActionEvent event){
        updateBtnState();
    }

    @FXML
    void onMinuteSelect(ActionEvent event){
        updateBtnState();
    }

    private DeskController closeDialog() {
        Scene scene = anchor.getScene();
        Stage window = (Stage)scene.getWindow();
        window.close();
        DeskController deskCtrl = DataContainer.deskCtrlMap.get(data.getId());
        return deskCtrl;
    }

    void updateBtnState(){
        Integer zero = 0;
        Integer value = hour.getValue();
        Integer mValue = minute.getValue();
        if(zero.equals(value) && zero.equals(mValue)){
            overtimeBtn.setDisable(true);
        }else{
            overtimeBtn.setDisable(false);
        }
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        Integer two = 2;
        closedTime = new Date();
        data = DataContainer.deskContainer.get(DataContainer.selectDeskId);
        clientService = ClientServiceImpl.getInstance();
        if( two.equals(data.getTimeLimit())){
            CheckOutResult playResult = clientService.checkOut(data,new Date());
            realTime.setText(playResult.getTotalTime());
            data.setIncome(playResult.getTotalMoney());
            income.setText(playResult.getTotalMoney().toString());
            countTotalIncome();
        }else{
            CheckOutResult result = clientService.checkOut(data,null);
            orgTime.setText(result.getTotalTime());
            amount.setText(result.getTotalMoney().toString());

            CheckOutResult playResult = clientService.checkOut(data,new Date());
            realTime.setText(playResult.getTotalTime());
            if (null != income){
                income.setText(playResult.getTotalMoney().toString());
            }

            CheckOutResult leftResult = checkOutLeft(result, playResult);
            leftTime.setText(leftResult.getTotalTime());
            if(null != leftAmount){
                leftAmount.setText(leftResult.getTotalMoney().toString());
            }
        }

        if(hour != null){
            hours = new ArrayList<>();
            for(int i = 0;i<25;i++){
                hours.add(i);
            }
            ObservableList<Integer> options = FXCollections.observableList(hours);
            hour.setItems(options);
        }

        if(minute != null){
            minutes = new ArrayList<>();
            for (int i=0;i<60;i++){
                minutes.add(i);
            }
            ObservableList<Integer> minOptions = FXCollections.observableList(minutes);
            minute.setItems(minOptions);
            hour.setValue(1);
            minute.setValue(0);
        }

        if(two.equals(data.getTimeLimit())){
            loadCartsData();
        }
    }

    private void countTotalIncome() {
        BigDecimal playIncome = data.getIncome();
        List<Cart> carts = data.getCartList();
        if(carts != null && carts.size() > 0){
            BigDecimal sailAmount = carts.stream().map(mp -> mp.getGoodsPrice().multiply(new BigDecimal(mp.getNum()))).reduce(BigDecimal.ZERO, (g1, g2) -> g1.add(g2));
            BigDecimal totalIncome = playIncome.add(sailAmount);
            total.setText(totalIncome.toString());
        }else{
            total.setText(playIncome.toString());
        }

    }

    @FXML
    void onNumberEdit(ActionEvent  event){
        System.out.println("Hello");
    }

    private void loadCartsData() {
        List<Cart> carts = data.getCartList();
        ObservableList<Cart> list = FXCollections.observableList(carts);
        goodsTable.setItems(list);
        goodsNameCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Cart, String>, ObservableValue<String>>() {
            @Override
            public ObservableValue<String> call(TableColumn.CellDataFeatures<Cart, String> param) {
                return new SimpleStringProperty(param.getValue().getGoodsName());
            }
        });

        goodsImgCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Cart, ImageView>, ObservableValue<ImageView>>() {
            @Override
            public ObservableValue<ImageView> call(TableColumn.CellDataFeatures<Cart, ImageView> param) {
                String imgUrl = param.getValue().getImgUrl();
                Image img = new Image(DataContainer.loadImageUrl + "/"+ imgUrl);
                ImageView imgView = new ImageView(img);
                imgView.setFitHeight(40);
                imgView.setFitWidth(40);
                return new SimpleObjectProperty<ImageView>(imgView);
            }
        });

        goodsPriceCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Cart, BigDecimal>, ObservableValue<BigDecimal>>() {
            @Override
            public ObservableValue<BigDecimal> call(TableColumn.CellDataFeatures<Cart, BigDecimal> param) {
                SimpleObjectProperty<BigDecimal> price = new SimpleObjectProperty(param.getValue().getGoodsPrice().setScale(2, BigDecimal.ROUND_HALF_UP));
                return price;
            }
        });

        goodsNumCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Cart, Integer>, ObservableValue<Integer>>() {
            @Override
            public ObservableValue<Integer> call(TableColumn.CellDataFeatures<Cart, Integer> param) {
                ObservableValue<Integer> val = new SimpleObjectProperty<>(param.getValue().getNum());
                return val;
            }
        });

        totalCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Cart, BigDecimal>, ObservableValue<BigDecimal>>() {
            @Override
            public ObservableValue<BigDecimal> call(TableColumn.CellDataFeatures<Cart, BigDecimal> param) {
                BigDecimal price = param.getValue().getGoodsPrice();
                Integer num = param.getValue().getNum();
                BigDecimal totalAmount = price.multiply(new BigDecimal(num)).setScale(2, BigDecimal.ROUND_HALF_UP);
                ObservableValue<BigDecimal> total = new SimpleObjectProperty<>(totalAmount);
                return total;
            }
        });

        playerNameCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Cart, String>, ObservableValue<String>>() {
            @Override
            public ObservableValue<String> call(TableColumn.CellDataFeatures<Cart, String> param) {
                return new SimpleObjectProperty<>(param.getValue().getPlayerName());
            }
        });

        actRefundBtn.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Cart, Button>, ObservableValue<Button>>() {
            @Override
            public ObservableValue<Button> call(TableColumn.CellDataFeatures<Cart, Button> param) {
               Button button = new Button();
               button.setText("退货");
               button.setOnAction(new EventHandler<ActionEvent>() {
                   @Override
                   public void handle(ActionEvent event) {
                       Platform.runLater(new Runnable() {
                           @Override
                           public void run() {
                               Cart cart = param.getValue();
                               int num =  cart.getNum();
                               Result result = clientService.removeCart(cart);
                               if(result.getCode() == 200){
                                   list.remove(cart);
                                   goodsTable.setItems(list);
                                   countTotalIncome();
                               }
                           }
                       });
                   }
               });
               button.setPrefWidth(40);
               button.setPrefHeight(16);
               SimpleObjectProperty<Button> btnProp = new SimpleObjectProperty<>(button);
               return btnProp;
            }
        });

    }

    private CheckOutResult checkOutLeft(CheckOutResult result, CheckOutResult playResult) {
        BigDecimal orgMinutes = result.getHour().multiply(new BigDecimal(60)).add(result.getMinute());
        BigDecimal playMinutes = playResult.getHour().multiply(new BigDecimal(60)).add(playResult.getMinute());
        BigDecimal minutes = orgMinutes.subtract(playMinutes);
        BigDecimal leftAmount = result.getTotalMoney().subtract(playResult.getTotalMoney());
        BigDecimal hours = minutes.divide(new BigDecimal(60),0,BigDecimal.ROUND_DOWN);
        BigDecimal showMinutes = minutes.subtract(hours.multiply(new BigDecimal(60)));
        return new CheckOutResult(leftAmount,hours,showMinutes);
    }

}
